<template>
  <div class="video">
    <div class="loading" v-if="loading">
      <span class="text" style="--i: 1">视</span>
      <span class="text" style="--i: 2">频</span>
      <span class="text" style="--i: 3">缓</span>
      <span class="text" style="--i: 4">冲</span>
      <span class="text" style="--i: 5">中</span>
      <span class="text" style="--i: 6">·</span>
      <span class="text" style="--i: 7">·</span>
      <span class="text" style="--i: 8">·</span>
      <span>{{ pecent }}</span>
    </div>
    <video
      src="../assets/images/video.mp4"
      ref="videoRef"
      muted
      autoplay
      loop
      controls
      @playing="onPlaying"
      @waiting="onWaiting"
    ></video>
  </div>

  <!-- playing事件: 在视频因缓冲而暂停或就绪后触发 -->
  <!-- waiting事件: 在视频需要缓冲下一帧而停止时触发 -->
</template>

<script setup>
import { onBeforeMount, onMounted, ref } from "vue";

const loading = ref(true);
const videoRef = ref(null);

function onPlaying() {
  loading.value = false;
  startBufferCheck();
}

function onWaiting() {
  loading.value = true;
}

let lastSpeedUpdate = ref(Date.now());
let lastBuffered = ref(0);
let speedKbps = ref(10);

// 动态计算阈值
function calculateNetworkSpeed() {
  const now = Date.now();
  if (!videoRef.value?.buffered.length) return;

  const bufferedNow = videoRef.value.buffered.end(0);
  const timeDelta = (now - lastSpeedUpdate.value) / 1000; // 转换为秒
  console.log(now);
  const bytesDelta = bufferedNow - lastBuffered.value;

  // 每秒可以缓冲的视频时长
  speedKbps.value = bytesDelta / timeDelta;
  if (speedKbps.value < 1) {
    speedKbps.value = 1;
  }
  lastSpeedUpdate.value = now;
  lastBuffered.value = bufferedNow;
}

let checkInterval = ref(null);
function startBufferCheck() {
  if (checkInterval.value) clearInterval(checkInterval.value);
  checkInterval.value = setInterval(() => {
    if (!videoRef.value.buffered.length || videoRef.value.paused) return;
    // 获取当前缓冲区 的末尾时间
    const bufferedEnd = videoRef.value.buffered.end(0);
    console.log(videoRef.value.buffered, "=====缓冲范围");
    console.log(bufferedEnd, "获取当前缓冲区的末尾时间");
    // 此时视频已经完全加载完毕
    if (bufferedEnd === videoRef.value.duration) {
      clearInterval(checkInterval.value);
      videoRef.value.play();
      loading.value = false;
      return;
    }
    const currentTime = videoRef.value.currentTime;
    console.log(bufferedEnd, currentTime, "当前缓冲区的末尾时间和当前播放时间");
    // 如果播放位置接近缓冲区末尾，暂停并等待加载
    if (bufferedEnd - currentTime < speedKbps.value) {
      loading.value = true;
      videoRef.value.pause();
      console.log("缓冲区不足，暂停播放");
      calculateNetworkSpeed();
      function checkResume() {
        if (videoRef.value.buffered.end(0) - currentTime >= speedKbps.value) {
          // 如果缓冲区已经超过缓冲区阈值，继续播放
          videoRef.value.play();
          loading.value = false;
        } else {
          // 继续等待加载
          requestAnimationFrame(checkResume);
        }
      }

      checkResume();
    } else {
      loading.value = false;
    }
  }, 1000); // 每秒检查一次
}

let pecent = ref(null);
onMounted(() => {
  videoRef.value.addEventListener("progress", () => {
    // 视频已缓冲时间范围
    if (videoRef.value.buffered.length > 0) {
      const bufferedEnd = videoRef.value.buffered.end(
        videoRef.value.buffered.length - 1
      );
      // 返回当前视频的长度，以秒为单位
      const duration = videoRef.value.duration;
      pecent.value = ((bufferedEnd / duration) * 100).toFixed(2) + "%";
      console.log(bufferedEnd, duration, "====");
    }
  });
});

onBeforeMount(() => {
  videoRef.value?.removeEventListener("progress", () => {});
  clearInterval(checkInterval.value);
});
</script>

<style scoped lang="less">
@keyframes upDown {
  0% {
    transform: translateY(0);
  }

  20% {
    transform: translateY(-12px);
  }

  40%,
  100% {
    transform: translateY(0);
  }
}

.video {
  width: 100%;
  height: 100%;
  position: relative;

  video {
    width: 100%;
    height: 100%;
  }

  .loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 20px;
    letter-spacing: 5px;
    color: #fff;

    .text {
      display: inline-block;
      animation: upDown 1.5s ease-in-out infinite;
      animation-delay: calc(0.1s * var(--i));
    }
  }
}
</style>
